package com.core.mvc.service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import com.core.db.Connector;
import com.core.mvc.Require;
import com.core.mvc.config.ConfigBean;
import com.core.mvc.config.ConfigParser;

/**
 * 用户服务引擎
 * 
 * 管理定义的服务分发客户端请求
 * 
 * @author 殷田
 *
 */
public class ServiceEngine
{
	private static ServiceEngine instance;
	private ConfigBean config;
	private Map< String, ServiceBean > services = new HashMap< String, ServiceBean >();
	private AtomicBoolean isStart = new AtomicBoolean( false );

	private ServiceEngine()
	{

	}

	public static ServiceEngine get()
	{
		if ( instance == null )
		{
			synchronized ( ServiceEngine.class )
			{
				if ( instance == null )
				{
					instance = new ServiceEngine();
				}
			}
		}
		return instance;
	}

	public void startup()
	{
		if ( !isStart.get() )
		{
			isStart.set( true );
			config = ConfigParser.getParser().parse();
			loadServices( config );
			loadDB( config );
		}
	}

	public void reStartup()
	{
		isStart.set( false );
		startup();
	}

	public void dispatchRequire( Require require )
	{
		if ( require != null )
		{
			try
			{
				doDispatchRequire( require );
			}
			catch ( IllegalArgumentException e )
			{
				try
				{
					require.getResp().sendError( 404,
									"not found: " + require.getReq().getRequestURI() );
				}
				catch ( Exception e1 )
				{
					e1.printStackTrace();
				}
			}
			catch ( Exception e )
			{
				e.printStackTrace();
				try
				{
					require.getResp().sendError( 500, e.getMessage() );
				}
				catch ( Exception e1 )
				{
					e1.printStackTrace();
				}
			}
		}
	}

	/**
	 * 加载服务
	 * 
	 * @param config
	 */
	private void loadServices( ConfigBean config )
	{
		services = ServiceLoader.getLoader().load( config.getInit() );
	}

	private void loadDB( ConfigBean config )
	{
		try
		{
			Connector.get().create( config.getDatabase() );
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}

	/**
	 * 请求分发
	 *
	 * @param info
	 */
	private void doDispatchRequire( Require require ) throws IllegalArgumentException
	{
		if ( require != null && require.getServiceName() != null
						&& require.getActionName() != null )
		{
			dispatchService( require );
		}
	}

	/**
	 * 服务分发
	 * 
	 * @param require
	 */
	private void dispatchService( Require require ) throws IllegalArgumentException
	{
		if ( !services.containsKey( require.getServiceName() ) )
		{
			throw new IllegalArgumentException( "no such service" );
		}
		ServiceBean serviceBean = services.get( require.getServiceName() );
		IFilterHandler< Require > filterHandler = serviceBean.getFilterHandler();

		if ( filterHandler == null || filterHandler.doFilter( require ) )
		{
			dispatchAction( require, serviceBean );
		}else
		{
			try
			{
				require.getResp().sendError( 404, "Resources do not exist" );
			}
			catch ( Exception e )
			{
				e.printStackTrace();
			}
		}
	}

	private void dispatchAction( Require require, ServiceBean serviceBean )
					throws IllegalArgumentException
	{
		if ( serviceBean.getAction( require.getActionName() ) == null )
		{
			throw new IllegalArgumentException( "no such action" );
		}
		ActionBean actionBean = serviceBean.getAction( require.getActionName() );
		IFilterHandler< Require > filterHandler = actionBean.getFilterHandler();
		if ( filterHandler == null || filterHandler.doFilter( require ) )
		{
			try
			{
				actionBean.getMethod().invoke( serviceBean.getTarget(), require );
			}
			catch ( Exception e )
			{
				e.printStackTrace();
				throw new IllegalArgumentException( "Service run failure", e );
			}
		}else
		{
			try
			{
				require.getResp().sendError( 404, "Resources do not exist" );
			}
			catch ( Exception e )
			{
				e.printStackTrace();
			}
		}
	}

	public ConfigBean getConfig()
	{
		return config;
	}

	public void destroy()
	{
		isStart.set( false );
		services.clear();
		config = null;
	}
}
